﻿using System;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace VMExplorer.Win32
{
	// Heaps
	partial class Native
	{
		#region :: Enums ::

		[Flags]
		public enum HEAP_FLAGS : uint
		{
			HEAP_NO_SERIALIZE = 0x00000001,
			HEAP_GROWABLE = 0x00000002,
			HEAP_GENERATE_EXCEPTIONS = 0x00000004,
			HEAP_ZERO_MEMORY = 0x00000008,
			HEAP_REALLOC_IN_PLACE_ONLY = 0x00000010,
			HEAP_TAIL_CHECKING_ENABLED = 0x00000020,
			HEAP_FREE_CHECKING_ENABLED = 0x00000040,
			HEAP_DISABLE_COALESCE_ON_FREE = 0x00000080,
			HEAP_CREATE_ALIGN_16 = 0x00010000,
			HEAP_CREATE_ENABLE_TRACING = 0x00020000,
			HEAP_CREATE_ENABLE_EXECUTE = 0x00040000
		};

		[Flags]
		public enum HEAP_ENTRY_FLAGS : byte
		{
			Busy = 0x01,
			ExtraPresent = 0x02,
			FillPattern = 0x04,
			VirtualAlloc = 0x08,
			LastEntry = 0x10,
			FFU1 = 0x20,
			FFU2 = 0x40,
			NoCoalesce = 0x80
		};

		//[Flags]
		//public enum PROCESS_HEAP_FLAGS : ushort
		//{
		//  PROCESS_HEAP_FREE = 0x0000,

		//   <summary>
		//   If this flag is set, the heap element is located at the beginning of a region of contiguous virtual memory in use by the heap.
		//   If this flag is set, the lpData member of the structure points to the first virtual address used by the region; the cbData member specifies the total size, in bytes, of the address space that is reserved for this region; and the cbOverhead member specifies the size, in bytes, of the heap control structures that describe the region.
		//   If this flag is set, the Region structure becomes valid. The dwCommittedSize, dwUnCommittedSize, lpFirstBlock, and lpLastBlock members of the structure contain additional information about the region. 
		//   </summary>
		//  PROCESS_HEAP_REGION = 0x0001,

		//   <summary>
		//   If this flag is set, the heap element is located in a range of uncommitted memory within the heap region.
		//   If this flag is set, the lpData member points to the beginning of the range of uncommitted memory; the cbData member specifies the size, in bytes, of the range of uncommitted memory; and the cbOverhead member specifies the size, in bytes, of the control structures that describe this uncommitted range. 
		//   </summary>
		//  PROCESS_HEAP_UNCOMMITTED_RANGE = 0x0002,

		//   <summary>
		//   If this flag is set, the heap element is an allocated block.
		//   If both this flag and the PROCESS_HEAP_ENTRY_MOVEABLE flag are set, the Block structure becomes valid. The hMem member of the Block structure contains a handle to the allocated, moveable memory block. 
		//   </summary>
		//  PROCESS_HEAP_ENTRY_BUSY = 0x0004,

		//   <summary>
		//   This flag is only valid if the PROCESS_HEAP_ENTRY_BUSY flag is set, indicating that the heap element is an allocated block.
		//   If this flag is valid and set, the block was allocated with the LMEM_MOVEABLE or GMEM_MOVEABLE flag, and the Block structure becomes valid. The hMem member of the Block structure contains a handle to the allocated, moveable memory block. 
		//   </summary>
		//  PROCESS_HEAP_ENTRY_MOVEABLE = 0x0010,

		//   <summary>
		//   This flag is only valid if the PROCESS_HEAP_ENTRY_BUSY flag is set, indicating that the heap element is an allocated block.
		//   If this flag is valid and set, the block was allocated with the GMEM_DDESHARE flag. For a discussion of the GMEM_DDESHARE flag, see GlobalAlloc . 
		//   </summary>
		//  PROCESS_HEAP_ENTRY_DDESHARE = 0x0020
		//}

		#endregion
		#region :: Structs ::

		[StructLayout (LayoutKind.Sequential, Size = 0x08)]
		public struct HEAP_ENTRY
		{
		  [Description("Self size (*8 bytes)")]
		  public UInt16 Size;
			[Description ("Previous chunk size (*8 bytes)")]
		  public UInt16 PreviousSize;
		  public byte SmallTagIndex;
		  public HEAP_ENTRY_FLAGS	EntryFlags;
		  public byte UnusedBytes;
		  public byte SegmentIndex;
		}


		[StructLayout (LayoutKind.Sequential, Size = 0x3C)]
		public struct HEAP_SEGMENT
		{
		  public HEAP_ENTRY Entry;
		  public UInt32 Signature;
		  public HEAP_FLAGS Flags;
		  public IntPtr Heap; // _HEAP*
		  public UInt32 LargestUnCommittedRange;
		  public IntPtr BaseAddress;
		  public UInt32 NumberOfPages;
		  public IntPtr FirstEntry; // HEAP_ENTRY*
		  public IntPtr LastValidEntry; // HEAP_ENTRY*
		  public UInt32 NumberOfUnCommittedPages;
		  public UInt32 NumberOfUnCommittedRanges;
		  public IntPtr UnCommittedRanges; // _HEAP_UNCOMMMTTED_RANGE*
		  public UInt16 AllocatorBackTraceIndex;
		  public UInt16 Reserved;
		  public IntPtr LastEntryInSegment; // _HEAP_ENTRY*
		};

		[StructLayout (LayoutKind.Sequential, Size = 0x20)]
		public struct HEAP_VIRTUALALLOCATED
		{
		  public LIST_ENTRY    VirtualAllocdBlocks;
		  public LIST_ENTRY    Unknown1;
		  public UInt32        Size;
		  public UInt32        Size2;
		  public UInt32        Unknown2;
		  public UInt32        Unknown3;
		};

		[StructLayout (LayoutKind.Explicit, Size = 0x588)]
		public struct HEAP
		{
		  [FieldOffset (0x000)]
		  public HEAP_ENTRY    HeapEntry;
		  [FieldOffset (0x008)]
		  public UInt32        Signature;
		  [FieldOffset (0x00C)]
		  public HEAP_FLAGS    Flags;
		  [FieldOffset (0x010)]
		  public UInt32        ForceFlags;
		  [FieldOffset (0x014)]
		  public UInt32        VirtualMemoryThreshold;
		  [FieldOffset (0x018)]
		  public UInt32        SegmentReserve;
		  [FieldOffset (0x01C)]
		  public UInt32        SegmentCommit;
		  [FieldOffset (0x020)]
		  public UInt32        DeCommitFreeBlockThreshold;
		  [FieldOffset (0x024)]
		  public UInt32        DeCommitTotalFreeThreshold;
		  [FieldOffset (0x028)]
		  public UInt32        TotalFreeSize;
		  [FieldOffset (0x02C)]
		  public UInt32        MaximumAllocationSize;
		  [FieldOffset (0x030)]
		  public UInt16        ProcessHeapsListIndex;
		  [FieldOffset (0x032)]
		  public UInt16        HeaderValidateLength;
		  [FieldOffset (0x034)]
		  public IntPtr        HeaderValidateCopy; // VOID* 
		  [FieldOffset (0x038)]
		  public UInt16        NextAvailableTagIndex;
		  [FieldOffset (0x03A)]
		  public UInt16        MaximumTagIndex;
		  [FieldOffset (0x03C)]
		  public IntPtr        TagEntries; //HEAP_TAG_ENTRY*
		  [FieldOffset (0x040)]
		  public IntPtr        UCRSegments; //HEAP_UCR_SEGMENT*
		  [FieldOffset (0x044)]
		  public IntPtr        UnusedUnCommittedRanges; // HEAP_UNCOMMMTTED_RANGE*
		  [FieldOffset (0x048)]
		  public UInt32        AlignRound;
		  [FieldOffset (0x04C)]
		  public UInt32        AlignMask;
		  [FieldOffset (0x050)]
		  public LIST_ENTRY    VirtualAllocdBlocks;
		  [MarshalAs (UnmanagedType.ByValArray, SizeConst = 64)]
		  [FieldOffset (0x058)]
		  public IntPtr[]      Segments; // HEAP_SEGMENT*

		  [MarshalAs (UnmanagedType.ByValArray, SizeConst = 16)]
		  [FieldOffset (0x158)]
		  public byte[]        FreeListsInUseBytes;

		  [FieldOffset (0x168)]
		  public UInt16        FreeListsInUseTerminate;
		  [FieldOffset (0x168)]
		  public UInt16        DecommitCount;

		  [FieldOffset (0x16A)]
		  public UInt16        AllocatorBackTraceIndex;
		  [FieldOffset (0x16C)]
		  public UInt32        NonDedicatedListLength;
		  [FieldOffset (0x170)]
		  public IntPtr        LargeBlocksIndex; //VOID* 
		  [FieldOffset (0x174)]
		  public IntPtr        PseudoTagEntries; //HEAP_PSEUDO_TAG_ENTRY*
		  [MarshalAs (UnmanagedType.ByValArray, SizeConst = 128)]
		  [FieldOffset (0x178)]
		  public LIST_ENTRY[]  FreeLists;
		  [FieldOffset (0x578)]
		  public IntPtr        LockVariable; // HEAP_LOCK*
		  [FieldOffset (0x57C)]
		  public IntPtr        CommitRoutine; // FUNCT_1FD_B18*
		  [FieldOffset (0x580)]
		  public IntPtr        FrontEndHeap; // VOID*
		  [FieldOffset (0x584)]
		  public UInt16        FrontHeapLockCount;
		  [FieldOffset (0x586)]
		  public byte          FrontEndHeapType;
		  [FieldOffset (0x587)]
		  public byte          LastSegmentIndex;
		};

		//[StructLayout (LayoutKind.Explicit, Size = 28)]
		//public struct PROCESS_HEAP_ENTRY
		//{
		//  Points to the data portion of the heap element.
		//  To initiate a HeapWalk heap enumeration, set lpData to NULL.
		//  If the PROCESS_HEAP_REGION bit flag is set in the wFlags member, lpData points to the first virtual address used by the region.
		//  If the PROCESS_HEAP_UNCOMMITTED_RANGE bit flag is set in wFlags, lpData points to the beginning of the range of uncommitted memory. 
		//  [FieldOffset (0)]
		//  public IntPtr lpData;

		//  Specifies the size, in bytes, of the data portion of the heap element.
		//  If the PROCESS_HEAP_REGION bit flag is set in wFlags, cbData specifies the total size, in bytes, of the address space that is reserved for this region.
		//  If the PROCESS_HEAP_UNCOMMITTED_RANGE bit flag is set in wFlags, cbData specifies the size, in bytes, of the range of uncommitted memory.
		//  [FieldOffset (4)]
		//  public uint cbData;

		//  Specifies the size, in bytes, of the data used by the system to maintain information about the heap element. 
		//  These overhead bytes are in addition to the cbData bytes of the data portion of the heap element.
		//  If the PROCESS_HEAP_REGION bit flag is set in wFlags, cbOverhead specifies the size, in bytes, of the heap control structures that describe the region.
		//  If the PROCESS_HEAP_UNCOMMITTED_RANGE bit flag is set in wFlags, cbOverhead specifies the size, in bytes, of the control structures that describe this uncommitted range.
		//  [FieldOffset (8)]
		//  public byte cbOverhead;

		//  Identifies the heap region that contains the heap element. 
		//  A heap consists of one or more regions of virtual memory, each with a unique region index.
		//  In the first heap entry returned for most heap regions, HeapWalk sets the PROCESS_HEAP_REGION flag in the wFlags member. 
		//  When this flag is set, the members of the Region structure contain additional information about the region.
		//  The HeapAlloc function sometimes uses the VirtualAlloc function to allocate large blocks from a growable heap. 
		//  The heap manager treats such a large block allocation as a separate region with a unique region index. 
		//  HeapWalk does not set the PROCESS_HEAP_REGION flag in the heap entry returned for a large block region, so the members of the Region structure are not valid. 
		//  You can use the VirtualQuery function to get additional information about a large block region.
		//  [FieldOffset (9)]
		//  public byte iRegionIndex;

		//  A set of bit flags that specify properties of the heap element. 
		//  Some of these flags affect the meaning of other members of this PROCESS_HEAP_ENTRY data structure. 
		//  [FieldOffset (10)]
		//  public PROCESS_HEAP_FLAGS wFlags;

		//  This structure is valid only if both the PROCESS_HEAP_ENTRY_BUSY and PROCESS_HEAP_ENTRY_MOVEABLE flags in wFlags are set.
		//  --------------------------------------------
		//  Contains a handle to the allocated, moveable memory block.
		//  [FieldOffset (12)]
		//  public IntPtr Block_hMem;
		//   Reserved; not used.
		//  [FieldOffset (16)]
		//  public uint Block_dwReserved_0;
		//  [FieldOffset (20)]
		//  public uint Block_dwReserved_1;
		//  [FieldOffset (24)]
		//  public uint Block_dwReserved_2;

		//  This structure is valid only if the PROCESS_HEAP_REGION flag is set in the wFlags member.
		//  --------------------------------------------
		//  Specifies the number of bytes in the heap region that are currently committed as free memory blocks, busy memory blocks, or heap control structures.
		//  This is an optional field that is set to zero if the number of committed bytes is not available. 
		//  [FieldOffset (12)]
		//  public uint Region_dwCommittedSize;
		//  Specifies the number of bytes in the heap region that are currently uncommitted.
		//  This is an optional field that is set to zero if the number of uncommitted bytes is not available. 
		//  [FieldOffset (16)]
		//  public uint Region_dwUnCommittedSize;
		//  Pointer to the first valid memory block in this heap region.
		//  [FieldOffset (20)]
		//  public IntPtr Region_lpFirstBlock;
		//  Pointer to the first invalid memory block in thisheap region. 
		//  [FieldOffset (24)]
		//  public IntPtr Region_lpLastBlock;
		//}

		//[StructLayout (LayoutKind.Explicit, Size = 0x10)]
		//public struct HEAP_FREE_CHUNK
		//{
		//  [FieldOffset (0x000)]
		//  public HEAP_ENTRY Entry;
		//  [FieldOffset (0x008)]
		//  public IntPtr NextChunk;
		//  [FieldOffset (0x008)]
		//  public IntPtr PreviousChunk;
		//}

		#endregion
		#region :: API ::

		//[DllImport ("kernel32.dll", SetLastError = true)]
		//public static extern IntPtr HeapCreate (uint flOptions, UIntPtr dwInitialSize, UIntPtr dwMaximumSize);

		//[DllImport ("kernel32.dll", SetLastError = true)]
		//public static extern IntPtr HeapAlloc (IntPtr hHeap, uint dwFlags, UIntPtr dwBytes);

		//[DllImport ("kernel32.dll", SetLastError = true)]
		//public static extern bool HeapWalk (IntPtr hHeap, ref PROCESS_HEAP_ENTRY lpEntry);

		//[DllImport ("kernel32.dll", SetLastError = true)]
		//public static extern IntPtr GetProcessHeap ();

		//[DllImport ("kernel32.dll", SetLastError = true)]
		//public static extern uint GetProcessHeaps (uint NumberOfHeaps, out IntPtr ProcessHeaps);

    [DllImport("mscoree.dll")]
    public static extern IntPtr GetProcessExecutableHeap();

		#endregion
	}


}